/*! \file visitordata.h
    \author HiddenSeeker

	Describes a visitor private data, used to create data
*/
#include "classsemantic.h"
#include "error.h"
#include "../templates/hstringlist.h"
#include <map>
#include "methodvisitor.h"
#include "methodchecker.h"
#include <set>

class SemanticVisitorData
{
 private:
		 /*! An errors
          */
		 std::vector<Error *>  m_errors; 
		 /*! A warnings
		  */
		 std::vector<Error *> m_warnings;
		 /*! Detected inheritance loop
		  */
		 std::vector< std::vector<std::string> > m_loops;
		 /*! Root class of visitor data
		  */
		 std::string m_rootclass;
		 /*! Root procedure of visitor data
		  */
		 std::string m_rootproc;
		 /*! Defines a routines. If method in routines was already scanned, does nothing
		  */
		 std::set<Compound *> m_routines;
		 /*! Scans inheritance for loop and errors that leads to non existence
			 \param[in] scanned scanned data
			 \param[in] loop    looped data
		  */
		 bool scanLoop(ClassTypeNode * scanned,std::vector<std::string> & loop);
		 /*! Scans all classes for inheritance loops
		  */
		 void scanForInheritanceLoops();

		 void addLibraryClass(const std::string & s, ClassSemantic * c);
		 /*! Creates all library classes with their functions
		  */
		 void createLibraryClasses();
		 void createInteger();
		 void createReal();
		 void createCharacter();
		 void createString();
		 void createBoolean();
		 void createStreams();
		 void createArrayType(const std::string & compatibleType);

		 bool isKnown(const std::string & name);

		 /*! Checks and marks root class and procedure
		  */ 
		 void checkAndMarkRootClassProcedure();
		 /*! Fixes clients of methods by adding proper clients
		  */
		 void fixClients();
		 /*! Formate a constructor list 
		  */
		 void findConstructors();
		 /*! Fills a conversion list
		  */
		 void fillConverters();
		 /*! Checks all argument lists of objects
		  */
		 void checkArgumentLists();
		 void addAnyIfNeed();
		 /*! Checks a duplicate inheritance in hierarchy 
		  */
		 void checkDuplicateInheritance();
		 bool m_should_print_tables;
		 bool m_should_print_code;
 public:
		 /*! Rejected classes data
		  */
	     std::vector<ClassSemantic *>           m_rejected_classes;
	     /*! Total list of classes data
          */
	     std::map<std::string,ClassSemantic *>  m_classes;
		 /*! List of library known classes
		  */
		 std::map<std::string,ClassSemantic *>  m_libraryclasses;
 public:
	     /*! Fills a data with classes, checking for errors
			 \param[in] root root node with all of the clases presented
			 \param[in] rootclass root class name
			 \param[in] rootproc  root procedure name
		  */ 
	     SemanticVisitorData(const std::vector<ListNode<ClassNode> *> & root,
							 const char * rootclass,
							 const char * rootproc);

		 /*! Destroys a semantic visitor data
		  */
		 ~SemanticVisitorData();

		 /*! Prints all errors
		  */
		 void print();
		 /*!  Returns if there are an errors
		  */
		 inline bool hasErrors() { return m_errors.size()!=0;}
		 /*!  Adds an error data
		  */
		 inline void add (Error * e) { m_errors.push_back(e); }
		 /*! Adds a warning data
		  */
		 inline void addWarning(Error * e) { m_warnings.push_back(e); }
		 /*! Tests, if class exists
		  */
		 inline bool exists(const std::string & name);
		 /*! Tests, if inheritance node is normal
		  */
		 bool isCorrect(ClassTypeNode * node,bool show_error=true);
		 /*! Perfoms all checks for data
			 \param[in] scand all data for errors
		  */
		 void scanForErrors();
		 /*! Prints tables for every class
		  */
		 void printAttrTables();
		 /*! Returns class by name
			 \param[in]  name       name of class
			 \param[out] className  class semantic node if exists
			 \return true if exists
		  */
		 bool getClassByName(const std::string & name,ClassSemantic *& className);
		 /*! Returns a class by name
			 \param[in] node with name
		  */
		 ClassSemantic * getClassByName(ClassTypeNode * node);
		 /*! Returns a class by name
		     \param[in] name 
		  */
		 ClassSemantic * getClassByName(const std::string & name);
		 /*! Fills inheritance tables, performing inheritance check
		  */
		 void fillInheritance();
		 /*! Generates flat shot forms
		  */
		 void generateFlatShotForms();
		 /*! Scans interfaces
		  */
		 void scanInterfaces();
		 /*! Ultimate check inheritance - checks for frozen and multiple inheritance
		  */
		 void checkFMI();

		 /*! Generates a constant pool
		     \param[in] print whether we should print it on a screen
		  */
		 void generateConstantTables(bool print);
		 /*! Generates a source code for all of classes
		     \param[in] print whether we should print it on a screen
		  */
		 void generateCode(bool print);
		 /*! Tests, whether it is a library class
		  */
		 bool isLibraryClass(const std::string & name)
		 {
			 m_libraryclasses.find(name)!=m_libraryclasses.end();
		 }
		 /*! Applies a visitor to all methods classes, scanning only relative classes
		  */
		 void applyVisitor(MethodVisitor * visitor);
		 /*! Marks as scanned current  compound
			 \return false if compund is absent in set 
		  */
		 bool markAsScanned(Compound * compound);
		 /*! Checks, whether one class in ancestor of another
			 \param[in] me                  self class
			 \param[in] possible_ancestor   ancestor, that it could be
			 \param[in] excluded            semantic that would be not scanned
		  */
		 bool isAncestor(const std::string & possible_ancestor,const std::string & me,InheritanceSemantic * excluded=NULL) ;
		 /*! Check, whether one class is derived from another
			 \param[in] me                    self class
			 \param[in] possible_derived      derived data
		  */
		 bool isDerived(const std::string & posssible_derived, const std::string & me);
		 /*! Test whether we should print tables
		  */
		 bool shouldPrintTables();
		 /*! Whether we should print code
		  */
		 bool shouldPrintCode();
};